﻿using System;
using System.Collections.Generic;
using System.Text;

using GeneralTool.CoreLibrary.Extensions;
using GeneralTool.CoreLibrary.Interfaces;

namespace GeneralTool.CoreLibrary.TaskLib
{
    /// <summary>
    /// 转换器
    /// </summary>
    public struct PackageConverter
    {
        /// <summary>
        /// Byte数组转为值
        /// </summary>
        public Func<byte[], Type, object> BufferToObjectFunc { get; set; }

        /// <summary>
        /// 值转为Byte数组
        /// </summary>
        public Func<object, byte[]> ObjectToBufferFunc { get; set; }

        public PackageConverter(Func<object, byte[]> o2b, Func<byte[], Type, object> b2o)
        {
            this.BufferToObjectFunc = b2o;
            this.ObjectToBufferFunc = o2b;
        }
    }

    /// <summary>
    /// 包服务相关帮助类
    /// </summary>
    public class PackageHelper
    {
        private readonly IJsonConvert jsonConverter;
        private readonly Encoding encoding;
        /// <summary>
        /// 据转换器字典
        /// </summary>
        private readonly Dictionary<Type, PackageConverter> converters = new Dictionary<Type, PackageConverter>();
        public PackageHelper(IJsonConvert jsonConvert = null, Encoding encoding = null)
        {
            if (jsonConvert == null) jsonConvert = new BaseJsonCovert();
            if (encoding == null) encoding = Encoding.UTF8;
            this.jsonConverter = jsonConvert;
            this.encoding = encoding;

            this.InitConverter();
        }


        ///// <summary>
        ///// 将字节数组转换为double
        ///// 支持4字节(int或float)和8字节(double)
        ///// </summary>
        ///// <param name="bytes">输入字节数组</param>
        ///// <returns>转换是否成功</returns>
        //public static double TryConvertToDouble(byte[] bytes)
        //{
        //    // 检查字节数组是否为空
        //    if (bytes == null)
        //        throw new ArgumentNullException(nameof(bytes), "输入字节数组不能为null");

        //    // 根据字节长度处理不同情况
        //    switch (bytes.Length)
        //    {
        //        case 4:
        //            // 对于4字节，这里需要明确是int还是float
        //            // 如果你有判断依据，可以在这里添加逻辑
        //            // 以下示例默认按float处理，你可以根据实际情况修改
        //            var intValue = BitConverter.ToInt32(bytes, 0);
        //            return intValue;

        //        case 8:
        //            // 8字节直接转换为double
        //            return BitConverter.ToDouble(bytes, 0);

        //        default:
        //            // 不支持的字节长度
        //            throw new ArgumentException(
        //                $"不支持的字节长度: {bytes.Length}，仅支持4或8字节",
        //                nameof(bytes)
        //            );
        //    }
        //}


        /// <summary>
        /// 初始化转换器
        /// </summary>
        private void InitConverter()
        {
            this.converters.Add(typeof(string), new PackageConverter((r) => this.encoding.GetBytes(r + ""), (r, b) => this.encoding.GetString(r)));
            this.converters.Add(typeof(byte), new PackageConverter((r) => new byte[] { Convert.ToByte(r) }, (r, b) => r[0]));
            this.converters.Add(typeof(short), new PackageConverter((r) => BitConverter.GetBytes(Convert.ToInt16(r)), (r, b) => BitConverter.ToInt16(r, 0)));
            this.converters.Add(typeof(sbyte), new PackageConverter((r) => BitConverter.GetBytes((short)Convert.ToSByte(r)), (r, b) => (sbyte)r[0]));
            this.converters.Add(typeof(int), new PackageConverter((r) => BitConverter.GetBytes(Convert.ToInt32(r)), (r, b) => BitConverter.ToInt32(r, 0)));
            this.converters.Add(typeof(long), new PackageConverter((r) => BitConverter.GetBytes(Convert.ToInt64(r)), (r, b) => BitConverter.ToInt64(r, 0)));
            this.converters.Add(typeof(ushort), new PackageConverter((r) => BitConverter.GetBytes(Convert.ToUInt16(r)), (r, b) => BitConverter.ToUInt16(r, 0)));
            this.converters.Add(typeof(uint), new PackageConverter((r) => BitConverter.GetBytes(Convert.ToUInt32(r)), (r, b) => BitConverter.ToUInt32(r, 0)));
            this.converters.Add(typeof(ulong), new PackageConverter((r) => BitConverter.GetBytes(Convert.ToUInt64(r)), (r, b) => BitConverter.ToUInt64(r, 0)));
            this.converters.Add(typeof(double), new PackageConverter((r) => BitConverter.GetBytes(Convert.ToDouble(r)), (r, b) => BitConverter.ToDouble(r,0)));
            this.converters.Add(typeof(float), new PackageConverter((r) => BitConverter.GetBytes(Convert.ToSingle(r)), (r, b) => BitConverter.ToSingle(r, 0)));
            this.converters.Add(typeof(decimal), new PackageConverter((r) => BitConverter.GetBytes(Convert.ToDouble(r)), (r, b) => BitConverter.ToSingle(r, 0)));
            this.converters.Add(typeof(bool), new PackageConverter((r) => BitConverter.GetBytes(Convert.ToBoolean(r)), (r, b) => BitConverter.ToBoolean(r, 0)));
            this.converters.Add(typeof(char), new PackageConverter((r) => BitConverter.GetBytes(Convert.ToChar(r)), (r, b) => BitConverter.ToChar(r, 0)));
            this.converters.Add(typeof(byte[]), new PackageConverter((r) => (byte[])r, (r, b) => r));
            this.converters.Add(typeof(char[]), new PackageConverter((r) => encoding.GetBytes((char[])r), (r, b) => encoding.GetChars(r)));
            //this.converters.Add(typeof(System.Drawing.Point), new PackageConverter(o2b: o =>
            //{
            //    var p = (System.Drawing.Point)o;
            //    var p2 = p.ToWindowPoint();
            //}, b2o: (b, t) =>
            //{

            //});

            this.converters.Add(typeof(System.Drawing.Bitmap), new PackageConverter(
                o2b: o =>
            {
                using (var bitmap = (System.Drawing.Bitmap)o)
                {
                    using (var ms = new System.IO.MemoryStream())
                    {
                        var rawFormat = bitmap.RawFormat;
                        var have = bitmap.RawFormat.HaveImageCodecInfo();
                        if (!have)
                        {
                            var id = "image/jpeg".GetEncoderInfo().FormatID;
                            rawFormat = new System.Drawing.Imaging.ImageFormat(id);
                        }
                        bitmap.Save(ms, rawFormat);
                        return ms.ToArray();
                    }
                }
            },
            b2o: (b, t) =>
            {
                //将字节流转为bitmap
                var ms = new System.IO.MemoryStream(b);

                return new System.Drawing.Bitmap(ms);

            }));
            this.converters.Add(typeof(object), new PackageConverter(r => this.encoding.GetBytes(this.jsonConverter.SerializeObject(r)), (r, b) => this.jsonConverter.DeserializeObject(this.encoding.GetString(r), b)));
        }


        /// <summary>
        /// 获取转换器字典
        /// </summary>
        /// <returns></returns>
        public Dictionary<Type, PackageConverter> GetConverters()
        {
            return this.converters;
        }

        /// <summary>
        /// 更新转换器
        /// </summary>
        /// <param name="type"></param>
        /// <param name="converter"></param>
        public void UpdateConverter(Type type, PackageConverter converter)
        {
            if (this.converters.TryGetValue(type, out _))
            {
                this.converters[type] = converter;
            }
        }

        /// <summary>
        /// 添加转换器
        /// </summary>
        /// <param name="type"></param>
        /// <param name="converters"></param>
        public void AddConverter(Type type, PackageConverter converters)
        {
            this.converters.Add(type, converters);
        }
    }
}
